package com.example.demo.localLock.aspect;

import com.google.common.cache.Cache;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class NoRepeatSubmitAspect {

    private Logger logger =LoggerFactory.getLogger(NoRepeatSubmitAspect.class);

    @Autowired
    private Cache cache;

    /**
     * 防止重复提交 -- 根据请求参数防止重复提交问题
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(* com.example.demo.localLock.controller..*(..)) && @annotation(com.example.demo.localLock.annotion.NotRepeatSubmit)")
    public synchronized Object aroundParam(ProceedingJoinPoint proceedingJoinPoint){
        HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        StringBuilder stringBuilder= new StringBuilder();
        request.getParameterMap().keySet().forEach(x->{
            stringBuilder.append("x = "+x+" y = "+request.getParameter(x));
        });
        String key = stringBuilder.toString() + "-" + request.getServletPath();
        logger.info("key={}",key);
        if (cache.getIfPresent(key) == null){
            try {
                cache.put(key,key);
                return proceedingJoinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }else {
            logger.info("重复提交！");
            return "重复提交";
        }
        return null;
    }

    /**
     * 防止重复提交 -- 根据请求SessionID防止重复提交问题
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(* com.example.demo.localLock.controller..*(..)) && @annotation(com.example.demo.localLock.annotion.LocalLock)")
    public synchronized Object aroundSessionID(ProceedingJoinPoint proceedingJoinPoint){
        String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
        String key = sessionId + ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest().getRequestURI();

        if (StringUtils.isEmpty(key)){
            cache.put(key,key);
            try {
                return proceedingJoinPoint.proceed();
            } catch (Throwable throwable) {
                throw new RuntimeException("请勿重复提交！");
            }
        }else {
            return "请勿重复提交";
        }
    }
}
